package nsoft.swing.component;

import java.lang.ref.WeakReference;
import java.math.BigDecimal;

import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

import nsoft.util.BeanUtilities;

public class NTextDocument extends PlainDocument implements BeanBinder {

	/**
	 * serialVersionUID = 1L.
	 */
	public static String DOUBLE_PATTERN = "[-]?[0-9]*[.]?[0-9]*";
	public static String LONG_PATTERN = "[-]?[0-9]*";
	private static final long serialVersionUID = 1L;
	private boolean updateInstantly = true;
	private ParseHelper parseHelper;
	private String property;
	private WeakReference<Object> beanRef;

	public NTextDocument(Object bean, String property) {
		if (bean != null && property != null) {
			this.beanRef = new WeakReference<Object>(bean);
			this.property = property;
			init(BeanUtilities.getFieldType(beanRef.get(), property));
		}
	}

	public NTextDocument() {
	}

	protected void init(Class<?> propClass) {
		if (propClass.equals(Short.class)) {
			parseHelper = new ParseHelper(ParseHelper.TYPE_SHORT);
			setDocumentFilter(new NDocumentFilter(LONG_PATTERN));
		} else if (propClass.equals(Integer.class)) {
			parseHelper = new ParseHelper(ParseHelper.TYPE_INT);
			setDocumentFilter(new NDocumentFilter(LONG_PATTERN));
		} else if (propClass.equals(Long.class)) {
			parseHelper = new ParseHelper(ParseHelper.TYPE_LONG);
			setDocumentFilter(new NDocumentFilter(LONG_PATTERN));
		} else if (propClass.equals(Double.class)) {
			parseHelper = new ParseHelper(ParseHelper.TYPE_DOUBLE);
			setDocumentFilter(new NDocumentFilter(DOUBLE_PATTERN));
		} else if (propClass.equals(BigDecimal.class)) {
			parseHelper = new ParseHelper(ParseHelper.TYPE_BIG_DECIMAL);
			setDocumentFilter(new NDocumentFilter(DOUBLE_PATTERN));
		} else if (propClass.equals(String.class)) {
			parseHelper = new ParseHelper(ParseHelper.TYPE_STRING);
			setDocumentFilter(new NDocumentFilter(null));
		} else {
			parseHelper = new ParseHelper(ParseHelper.TYPE_UNKNOWN);
			setDocumentFilter(new NDocumentFilter(null));
		}
	}

	public boolean isUpdateInstantly() {
		return updateInstantly;
	}

	public void setUpdateInstantly(boolean updateInstantly) {
		this.updateInstantly = updateInstantly;
	}

	public String getPattern() {
		return ((NDocumentFilter) getDocumentFilter()).getPattern();
	}

	public void setPattern(String pattern) {
		((NDocumentFilter) getDocumentFilter()).setPattern(pattern);
	}

	public ParseHelper getParseHelper() {
		return parseHelper;
	}

	public void setParseHelper(ParseHelper parseHelper) {
		this.parseHelper = parseHelper;
	}

	public String getProperty() {
		return property;
	}

	public void setProperty(String property) {
		this.property = property;
	}

	public Object getBean() {
		return beanRef.get();
	}

	public void setBean(Object bean) {
		beanRef = new WeakReference<Object>(bean);
		updateFromBean();
	}

	public boolean updateFromBean() {
		if (beanRef != null) {
			Object bean = beanRef.get();
			if (bean != null) {
				Object value = BeanUtilities.getProperty(bean, property);
				if (value != null) {
					try {
						super.insertString(0, value.toString(), null);
						return true;
					} catch (BadLocationException e) {
					}
				}
			}

		}
		return false;
	}

	public boolean updateBean() {
		if (updateInstantly && parseHelper != null) {
			try {
				BeanUtilities.setProperty(beanRef.get(), property, parseHelper
						.parse(getText(0, getLength())));
				return true;
			} catch (BadLocationException e) {

			}
		}
		return false;
	}
}
